package widget.slide;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;

import library.utils.DisplayUtil;
import widget.utils.TouchUtils;


public class SliderLayout extends HorizontalScrollView {
    private int mScreenWidth = DisplayUtil.getMetrics().widthPixels;
    //菜单的宽度
    private int mMenuWidth;
    private int mAutoRollBackWidth;
    private float mTouchSlop;

    private ViewGroup mContainer;
    private View mMenu;
    private View mContent;
    private OnDragListener onDragListener;
    private boolean draggable = true;
    private float percent = 1;

    public SliderLayout(Context context) {
        super(context);
        init();
    }

    public SliderLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public SliderLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public SliderLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    public void init() {
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        requestDisallowInterceptTouchEvent(true);
        setOverScrollMode(OVER_SCROLL_NEVER);
        setVerticalScrollBarEnabled(false);
        setHorizontalScrollBarEnabled(false);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mContent == null || mMenu == null) {
            mContainer = (ViewGroup) getChildAt(0);
            mMenu = mContainer.getChildAt(0);
            mContent = mContainer.getChildAt(1);

            mContent.getLayoutParams().width = mScreenWidth;
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    private Point getOffset(View view) {
        Rect rect = new Rect();
        Point offset = new Point();
        view.getGlobalVisibleRect(rect, offset);
        return offset;
    }


    private Drawable getGradientDrawable() {
        final int deep = 0xFF / 4;
        final int split = 3;
        final int[] colors = new int[split + 1];
        final int diff = deep / (split);
        for (int i = 0; i < split; i++) {
            colors[i] = Color.argb(deep - diff * i, 0, 0, 0);
        }
        colors[split] = Color.TRANSPARENT;
        return new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (mMenu != null && isOpen()) {
            int w = DisplayUtil.dp2px(3);
            Rect rect = new Rect(
                    mMenu.getRight(),
                    mMenu.getTop(),
                    mMenu.getRight() + w,
                    mMenu.getBottom());
            Drawable drawable = getGradientDrawable();
            drawable.setBounds(rect);
            drawable.draw(canvas);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (mMenuWidth == 0) {
            mMenuWidth = mMenu.getWidth();
            mAutoRollBackWidth = mMenuWidth * 2 / 3;
            if (changed) {
                this.scrollTo(mMenuWidth, 0);
            }
        }
    }

    @Override
    protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
        return 0;
    }

    public boolean isDraggable() {
        return draggable;
    }

    public void setDraggable(boolean draggable) {
        this.draggable = draggable;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }


    private TouchUtils.MoveListener moveListener = new TouchUtils.MoveListener();

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        moveListener.onTouch(ev);
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (isOpen() && isOutSide(mMenu, ev.getRawX(), ev.getRawY())) {
                    return true;
                }
            case MotionEvent.ACTION_MOVE:
                if (!draggable)
                    return false;
                if (moveListener.isMoveVertical()) {
                    return false;
                }
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    private boolean TOUCH_MOVED;
    protected float TOUCH_LAST_X;
    protected float TOUCH_LAST_Y;

    private VelocityTracker mVelocityTracker;

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getActionMasked();
        if (null == mVelocityTracker) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        final VelocityTracker tracker = mVelocityTracker;
        tracker.addMovement(ev);
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                tracker.clear();
                TOUCH_MOVED = false;
                TOUCH_LAST_X = ev.getX();
                TOUCH_LAST_Y = ev.getY();
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                if (!TOUCH_MOVED) {
                    float dx = Math.abs(ev.getX() - TOUCH_LAST_X);
                    float dy = Math.abs(ev.getY() - TOUCH_LAST_Y);
                    if (dx > mTouchSlop || dy > mTouchSlop) {
                        TOUCH_MOVED = true;
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                break;
            case MotionEvent.ACTION_OUTSIDE:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:

                if (!TOUCH_MOVED) {
                    if (isOpen() && isOutSide(mMenu, ev.getRawX(), ev.getRawY())) {
                        close();
                        releaseTracker();
                        return true;
                    }
                } else {
                    tracker.computeCurrentVelocity(500);
                    final float speed = tracker.getXVelocity();
                    final int base = DisplayUtil.getMetrics().widthPixels / 10;
                    final int scrollX = Math.abs(getScrollX());
                    if (scrollX < mTouchSlop) {
                        open();
                    } else if (Math.abs(speed) < base) {
                        if (scrollX > (mMenuWidth - mAutoRollBackWidth)) {
                            close();
                        } else {
                            open();
                        }
                    } else {
                        if (speed >= base) {
                            open();
                        } else {
                            close();
                        }
                    }
                    releaseTracker();
                    return true;
                }
                releaseTracker();
                break;
        }
        return super.onTouchEvent(ev);
    }

    public void releaseTracker() {
        if (mVelocityTracker != null) {
            mVelocityTracker.clear();
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }

    @Override
    public void fling(int velocityX) {
        super.fling(velocityX);
    }


    private boolean isOutSide(View v, float rawX, float rawY) {
        Rect rect = new Rect();
        v.getGlobalVisibleRect(rect);
        if (rect.right <= 0)
            return false;
        if (rawX > rect.left && rawX < rect.right && rawY > rect.top && rawY < rect.bottom) {
            return false;
        } else {
            return true;
        }
    }

    public boolean isOpen() {
        Rect rect = new Rect();
        Point offset = new Point();
        mContent.getGlobalVisibleRect(rect, offset);
//        Logger.simple(String.format("Rect(%d,%d,%d,%d)(%d,%d);offset(%d,%d)",
//                rect.left, rect.top, rect.right, rect.bottom,
//                rect.width(), rect.hashCode(),
//                offset.x, offset.y));
        return offset.x > 0;
    }

    public void setAvailable(boolean b) {
        ViewGroup.LayoutParams lp = getLayoutParams();
        lp.width = b ? DisplayUtil.getMetrics().widthPixels : 0;
        setLayoutParams(lp);
    }

    //打开菜单
    public void open() {
        this.smoothScrollTo(0, 0);
        if (onDragListener != null) {
            onDragListener.onOpen();
        }
    }

    //关闭菜单
    public void close() {
        this.smoothScrollTo(mMenuWidth, 0);
        if (onDragListener != null) {
            onDragListener.onClose();
        }
    }

    //关闭菜单
    public void dismiss() {
        this.scrollTo(mMenuWidth, 0);
        if (onDragListener != null) {
            onDragListener.onClose();
        }
    }

    //切换菜单状态
    public void toggle() {
        if (isOpen()) {
            close();
        } else {
            open();
        }
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        percent = 1 - l * 1.0f / mMenuWidth;
        float leftScale = 1 - 0.3f * percent;
        float rightScale = 0.8f + percent * 0.2f;

//        ViewHelper.setScaleX(mMenu, leftScale);
//        ViewHelper.setScaleY(mMenu,  eftScale);
//        ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - percent));
//        ViewHelper.setTranslationX(mMenu, mMenuWidth * percent * 0.7f);
//        ViewHelper.setPivotX(mContent, 0);

//        ViewCompat.setTranslationX(mMenu, mMenuWidth * percent );
//        ViewCompat.setPivotY(mContent, 0);
//        ViewHelper.setPivotY(mContent, mContent.getHeight() / 2);
//        ViewHelper.setScaleX(mContent, rightScale);
//        ViewHelper.setScaleY(mContent, rightScale);
        if (onDragListener != null) {
            onDragListener.onDrag(percent);
        }
        if (!(mContent instanceof ViewGroup)
                || ((ViewGroup) mContent).getChildCount() == 0) {
            ViewCompat.setAlpha(mContent, percent * .35F);
        }
    }


    public void setOnDragListener(OnDragListener onDragListener) {
        this.onDragListener = onDragListener;
    }

    public interface OnDragListener {
        public void onOpen();

        public void onClose();

        public void onDrag(float percent);
    }
}